package cn.wgx.commons.util;

import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry;
import org.apache.commons.compress.archivers.sevenz.SevenZFile;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipFile;

import java.io.*;
import java.util.ArrayList;
import java.util.Enumeration;

/**
 * 解压缩zip,7z
 * 读取压缩文件内文本
 */
public class CompressFile {

    /**
     * 读文本文件: 7z, zip
     * @param packagePath
     * @param filePath
     * @return
     */
    public static String readPackageFile(String packagePath, String filePath){
        String ext = StringUtils.getFileExt(packagePath);
        switch(ext){
            case "7z": return read7z(packagePath, filePath);
            case "zip": return readZip(packagePath, filePath);
        }
        return null;
    }

    private static String readZip(String packagePath, String filePath) {
        BufferedInputStream br = null;
        ZipFile zipFile = null;
        try {
            zipFile = new ZipFile(packagePath);
            ZipArchiveEntry archiveEntry = zipFile.getEntry(filePath);
            br = new BufferedInputStream(zipFile.getInputStream(archiveEntry));
            byte []line = new byte[2048];
            StringBuffer sb = new StringBuffer();
            while(br.read(line) > 0){
                sb.append(new String(line));
            }
            return sb.toString();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
          close(br, null, zipFile);
        }
        return null;
    }

    private static String read7z(String packagePath, String filePath) {
        SevenZFile sevenZFile = null;
        try {
            sevenZFile = new SevenZFile(new File(packagePath));
            SevenZArchiveEntry entry = sevenZFile.getNextEntry();
            StringBuffer sb = new StringBuffer();
            while (entry != null) {
                if(filePath.equals(entry.getName())){
                    byte [] b = new byte[2048];
                    while(sevenZFile.read(b) > 0){
                        sb.append(new String(b));
                    }
                    break;
                }
                entry = sevenZFile.getNextEntry();
            }
            return sb.toString();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            close(null,null, sevenZFile);
        }
        return null;
    }

    /**
     * 解压缩: 7z, zip
     * @param filePath
     * @param targetPath
     * @return
     */
    public static ArrayList<String> unCompress(String filePath ,String targetPath){
        return unCompress(filePath,targetPath, 0);
    }

    /**
     * 解压缩: 7z, zip
     * @param filePath
     * @param targetPath
     * @param deep 解压目录层级
     * @return
     */
    public static ArrayList<String> unCompress(String filePath ,String targetPath, int deep){
        String ext = StringUtils.getFileExt(filePath);
        switch(ext){
            case "7z": return un7z(filePath, targetPath, deep);
            case "zip": return unZip(filePath, targetPath, deep);
        }
        return null;
    }

    /**
     * 解压文件,指定解压压缩包中文件名
     * @param filePath
     * @param tar
     * @throws IOException
     */
    public static ArrayList<String> unZip(String filePath , String tar, int deep)  {
        ZipFile zipFile = null;
        FileOutputStream fot = null;
        BufferedInputStream br = null;
        try {
            zipFile = new ZipFile(filePath,"gbk");
            Enumeration<ZipArchiveEntry> entries = zipFile.getEntries();
            ArrayList<String> list = new ArrayList<>();
            while(entries.hasMoreElements()){
                ZipArchiveEntry entry = entries.nextElement();
                String name = entry.getName();
                String []n = name.split("/");
                if(entry.isDirectory()){
                    if(n.length > deep){
                        continue;
                    }
                    new File(tar + File.separator + name).mkdirs();
                }else{
                    if(n.length-1 > deep){
                        continue;
                    }
                    br = new BufferedInputStream(zipFile.getInputStream(entry));
                    fot = new FileOutputStream(tar + File.separator + name);
                    byte []b = new byte[2048];
                    while(br.read(b) > 0){
                        fot.write(b);
                    }
                    close(br, fot, null);
                }
                list.add(name);
            }
            return list;
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            close(br, fot, zipFile);
        }
        return null;
    }



    public static ArrayList<String> un7z(String orgPath ,String tarpath, int deep)  {
        SevenZFile sevenZFile = null;
        FileOutputStream out = null;
        try {
            sevenZFile = new SevenZFile(new File(orgPath));
            ArrayList<String> list = new ArrayList<>();
            SevenZArchiveEntry entry = sevenZFile.getNextEntry();
            while (entry != null) {
                String name = entry.getName();
                String []n = name.split("/");
                if (entry.isDirectory()) {
                    if(n.length > deep){
                        entry = sevenZFile.getNextEntry();
                        continue;
                    }else new File(tarpath + File.separator + entry.getName()).mkdirs();
                }else{
                    if(n.length-1 > deep){
                        entry = sevenZFile.getNextEntry();
                        continue;
                    }
                    out = new FileOutputStream(tarpath
                            + File.separator + entry.getName());
                    byte[] content = new byte[2048];
                    while(sevenZFile.read(content) > 0){
                        out.write(content);
                    }
                    close(null, out, null);
                }
                list.add(name);
                entry = sevenZFile.getNextEntry();
            }
            return list;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            close(null, out, sevenZFile);
        }
        return null;
    }


    private static void close(InputStream inputStream,
                              OutputStream outputStream,
                              Closeable closeable){

        try {
            if(inputStream != null){
                inputStream.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            if(outputStream != null){
                outputStream.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            if(closeable != null){
                closeable.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
